/****************************************************************
 *This file is thread-one.c
 ****************************************************************/

#include "include.h"

// 注意需要修改本条值
#define HITMC_MODULE_CLOSE							0x00050002

//inner function declare
static void *pc_command_get_func(void *arg);
static unsigned char * pc_command_process_func(const unsigned char *arg, unsigned int len, unsigned int *return_len, int *commd_func, int socket_fd);
static void board_process_func(int func_num_value, cJSON *in_data_p,  cJSON *ack_data_p);

/****************************************************************
 *This function is thread1
 *	(1)create socket,listen port,process command
 ****************************************************************/
void *thread1(void *str)
{
	//inner variable
	pthread_t pth;
	int ret;

	int sockfd, new_fd;
	struct sockaddr_in my_addr;
	struct sockaddr_in their_addr;
	unsigned int sin_size;
	pthread_socket_message socket_one_client_message;

	int recvTimeout = SOCKET_REV_TIMETOUT;		
	int sendTimeout = SOCKET_SEND_TIMETOUT;	

	// 避免编译错误
	str = str;
	recvTimeout = recvTimeout;
	sendTimeout = sendTimeout;

	// 延时800ms
	usleep(800000);

	// 建立通信用套接字
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		fprintf(stderr,"sockfd create error!\n");
		system("touch sockfd_create_error");
		system("reboot");
		exit(1);
   	}

	// 绑定本地端口
	bzero(&my_addr, sizeof(my_addr));
	my_addr.sin_family=AF_INET;
	my_addr.sin_port=htons(NET_COMMAND_PORT);
	my_addr.sin_addr.s_addr = INADDR_ANY;
	if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
	{
		fprintf(stderr,"sockfd bind error!\n");
		system("touch sockfd_bind_error");
		system("reboot");
		exit(1);
	}

	// 监听端口
	if (listen(sockfd, SOMAXCONN) == -1)
	{
		fprintf(stderr,"sockfd listen error!\n");
		system("touch sockfd_listen_error");
		system("reboot");
		exit(1);
	}

	// 清空局部变量
	bzero(&their_addr, sizeof(their_addr));

	// 给出线程运行提示信息
	fprintf(stderr,"thread one running\n");

	// 并发服务器，进行提供服务
	while(1)
	{
		// 等待客户端连接
		sin_size = sizeof(struct sockaddr_in);
		if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
		{
			fprintf(stderr,"sockfd accept error!\n");
			continue;
		}

		// 填充客户端的IP和端口
		socket_one_client_message.client_addr = their_addr.sin_addr;
		socket_one_client_message.client_port = their_addr.sin_port;
		socket_one_client_message.sockfd = new_fd;

		// 设置发送和接收超时
		//setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&errno, sizeof(int));
		//setsockopt(new_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&sendTimeout, sizeof(int));

		// 提供迭代服务
		ret = 0;
		ret = ret;
		ret = pthread_create(&pth, NULL, pc_command_get_func, (void *)(&socket_one_client_message));
	}

	return NULL;
}

/****************************************************************
 *This function is pc_command_get_func
 *	(1)read command from network and  process command
 ****************************************************************/
static void *pc_command_get_func(void *arg)
{
	pthread_socket_message client_message;
	unsigned char net_command_buf[NET_COMMAND_BUF_LEN];
	unsigned char net_command_buf_ack[NET_COMMAND_BUF_LEN];
	ssize_t  net_command_buf_len;
	ssize_t  net_command_buf_len_ack;
	unsigned int client_addr;
	unsigned short client_port;
	
	// 用户动态存储正式数据包的缓冲区和长度
	unsigned char *cjson_packet_p = NULL;
	size_t cjson_packet_len = 0; 
	size_t cjson_count_len = 0; 
	unsigned char *cjson_packet_ret_p = NULL;
	size_t cjson_packet_ret_len = 0; 
	size_t cjson_ret_len = 0, cjson_count_ret_len = 0; 
	int ret = 0;
	ssize_t cjson_len = 0;

	int func_num = 0;
	
	// 将线程变成独立的线程
	pthread_detach(pthread_self());

	// 获取客户端参数
	client_message  = *((pthread_socket_message *)arg);

	// 填充客户端参数
	client_addr = ntohl(client_message.client_addr.s_addr);
	client_addr = client_addr;
	client_port = ntohs(client_message.client_port);
	client_port = client_port;

#ifdef	TST_CODE_SWITCH
	//fprintf(stderr,"client_addr: %x, client_port: %x\n", client_addr, client_port);
#endif

	// 循环处理当前任务
	while(1){

		// 清空数据缓冲区
		net_command_buf_len = 0;
		net_command_buf_len_ack = 0;
		bzero(net_command_buf, NET_COMMAND_BUF_LEN);
		bzero(net_command_buf_ack, NET_COMMAND_BUF_LEN);

		// 读取客户端发送的第一包数据，该数据包包含正式数据的长度
		net_command_buf_len = 0;
		net_command_buf_len = read(client_message.sockfd, net_command_buf, NET_COMMAND_BUF_LEN);

		// 客户端主动关闭连接
		if(net_command_buf_len <= 0){
			// 关闭连接
			close(client_message.sockfd);

			// 进行函数返回
			return(NULL);
		}

		// 获取下一包整体数据的长度
		cjson_packet_len = net_command_buf[0];
		cjson_packet_len <<= 8;
		cjson_packet_len |= net_command_buf[1];
		cjson_packet_len <<= 8;
		cjson_packet_len |= net_command_buf[2];
		cjson_packet_len <<= 8;
		cjson_packet_len |= net_command_buf[3];

		// 清空内存空间，用于存放CJSON正式网络数据包
		cjson_packet_p = NULL;
		cjson_packet_p = (unsigned char *)malloc(cjson_packet_len);

		// 进行后续数据处理
		if(cjson_packet_p == NULL){
			// 申请内存空间失败，返回0，用于异常处理
			net_command_buf_len_ack = 4;
			net_command_buf_ack[0] = 0;
			net_command_buf_ack[1] = 0;
			net_command_buf_ack[2] = 0;
			net_command_buf_ack[3] = 0;
			ret = 0;
			ret = write(client_message.sockfd, \
					net_command_buf_ack, \
					net_command_buf_len_ack);

			// 客户端主动关闭连接
			if(ret < 0){
				// 关闭连接
				close(client_message.sockfd);

				// 进行函数返回
				return(NULL);
			}

			// 出现问题，结束本次循环
			continue;
		} 
		
		// 申请内存空间成功，通知客户端
		net_command_buf_len_ack = 4;
		memcpy(net_command_buf_ack, \
				net_command_buf, \
				net_command_buf_len_ack);
		ret = 0;
		ret = write(client_message.sockfd, \
				net_command_buf_ack, \
				net_command_buf_len_ack);

		// 客户端主动关闭连接
		if(ret < 0){
			// 关闭连接
			close(client_message.sockfd);

			// 进行函数返回
			return(NULL);
		}

		// 分次读取CJSON数据包
		cjson_count_len = 0;
		while(cjson_count_len < cjson_packet_len){
			// 读取TCP数据包
			cjson_len = 0;
			cjson_len = read(client_message.sockfd, \
								&(cjson_packet_p[cjson_count_len]), \
								TCP_RECEIVE_ONCE_NUM);
			// 客户端主动关闭连接
			if(cjson_len <= 0){
				// 关闭连接
				close(client_message.sockfd);

				// 进行函数返回
				return(NULL);
			}

			// 递增接收数据长度
			cjson_count_len += cjson_len;
		}

		// 进行数据处理
		func_num = 0;
		cjson_packet_ret_p = NULL;
		cjson_packet_ret_len = 0;
		cjson_packet_ret_p = pc_command_process_func(cjson_packet_p, \
								(unsigned int)cjson_packet_len, \
								(unsigned int *)(&cjson_packet_ret_len), \
								&func_num, \
								client_message.sockfd);

		// 内存空间申请失败
		if((cjson_packet_ret_p == NULL) || \
			(cjson_packet_ret_len == 0)){
			// 释放内存空间
			free(cjson_packet_p);

			// 出现问题，结束本次循环
			continue;
		}

		// 返回正式数据包长度
		net_command_buf_len = 4;
		net_command_buf[0] = (unsigned char)(cjson_packet_ret_len >> 24);
		net_command_buf[1] = (unsigned char)(cjson_packet_ret_len >> 16);
		net_command_buf[2] = (unsigned char)(cjson_packet_ret_len >> 8);
		net_command_buf[3] = (unsigned char)(cjson_packet_ret_len >> 0);
		ret = 0;
		ret = write(client_message.sockfd, \
				net_command_buf, \
				net_command_buf_len);

		// 客户端主动关闭连接
		if(ret < 0){
			// 关闭连接
			close(client_message.sockfd);

			// 进行函数返回
			return(NULL);
		}

		// 客户端给出应答，是否可以接收
		net_command_buf_len_ack = 0;
		net_command_buf_len_ack = read(client_message.sockfd, \
										net_command_buf_ack, \
										NET_COMMAND_BUF_LEN);

		// 客户端主动关闭连接
		if(net_command_buf_len_ack <= 0){
			// 关闭连接
			close(client_message.sockfd);

			// 进行函数返回
			return(NULL);
		}

		// 上位机给出异常应答
		if((net_command_buf_ack[0] == 0) && \
			(net_command_buf_ack[1] == 0) && \
			(net_command_buf_ack[2] == 0) && \
			(net_command_buf_ack[3] == 0)){

			// 释放内存空间
			free(cjson_packet_p);
			free(cjson_packet_ret_p);

			// 出现问题，结束本次循环
			continue;
		}

		// 进行分包发送
		cjson_ret_len = 0;
		cjson_count_ret_len = cjson_packet_ret_len;
		while(cjson_count_ret_len > 0){
			// 数据发送给客户端
			ret = write(client_message.sockfd, &(cjson_packet_ret_p[cjson_ret_len]), cjson_count_ret_len);

			// 客户端主动关闭连接
			if(ret < 0){
				// 关闭连接
				close(client_message.sockfd);

				// 进行函数返回
				return(NULL);
			}

			// 计算下一包长度
			cjson_ret_len += ret;
			cjson_count_ret_len -= ret;
		}

		// 释放内存空间
		free(cjson_packet_p);
		free(cjson_packet_ret_p);

		// 如果判断时关卡，则关闭链接
		if(func_num == HITMC_MODULE_CLOSE){
			// 关闭连接
			close(client_message.sockfd);

			// 进行函数返回
			return(NULL);
		}
	}
}

/****************************************************************
 *This function is pc_command_process_func
 *	(1)process pc send control command function
 ****************************************************************/
static unsigned char * pc_command_process_func(const unsigned char *arg, unsigned int len, unsigned int *return_len, int *commd_func, int socket_fd)
{
	cJSON *pc_cmd_json = NULL;
	cJSON *ack_cmd_json = NULL;
	char *ack_arg = NULL;
	unsigned int ack_len = 0;
	int func_num_value;
	unsigned char *return_arg = NULL;
	
	// 将数据转化为CJSON格式
	pc_cmd_json = cJSON_Parse((char *)arg);

	// 开始进行解包处理
	if(pc_cmd_json != NULL){
		// 申请一个CJSON对象，用于存放返回值
		ack_cmd_json = cJSON_CreateObject();

		// 进行数据处理
		if(ack_cmd_json != NULL){
			// 获取指令码
			func_num_value = cJSON_GetNumberValue(cJSON_GetObjectItem(pc_cmd_json, "func_num"));

			// 填充函数功能码
			*commd_func = func_num_value;

			// 将socket的值传入
			cJSON_AddNumberToObject(ack_cmd_json, "socketfd", socket_fd);	

			// 进行数据处理
			board_process_func(func_num_value, pc_cmd_json, ack_cmd_json);

			// 将cjson转化为可发送的字符串
			ack_arg = cJSON_Print(ack_cmd_json);

			// 准备将CJSON个数转化为字符串
			if(ack_arg != NULL){
				// 获取字符串长度
				ack_len = strlen(ack_arg);

				// 获取应答数据包
				if(ack_len > 0){
					// 申请存放返回值的内存空间
					return_arg =  (unsigned char *)malloc(ack_len + 10);

					// 进行返回数据处理
					if(return_arg != NULL){
						// 将放回数据复制到申请的内存空间中
						memcpy(return_arg, ack_arg, ack_len + 10);
						*return_len = ack_len + 10;
					}
				}
			} 

			// 释放内存空间
			cJSON_free(ack_arg);
			cJSON_Delete(ack_cmd_json);
			cJSON_Delete(pc_cmd_json);
		} else {
			// 释放内存空间
			cJSON_Delete(pc_cmd_json);
		}
	}

	// 返回操作数据
	return return_arg;
}

/****************************************************************
 *This function is board_process_func
 *	(1)process board function
 ****************************************************************/
static void board_process_func(int func_code, cJSON *in_data_p,  cJSON *ack_data_p)
{
	unsigned temp_i = 0;

	for(temp_i = 0; temp_i < PC_COMMAND_NUM; temp_i ++){
		// 未找到合适的处理函数，退出
		if(pc_cmd_data[temp_i].pc_command_code == 0){
			break;
		}
		
		// 找到对应的处理函数，进行函数处理
		if(pc_cmd_data[temp_i].pc_command_code == func_code){
			pc_cmd_data[temp_i].pc_command_func(in_data_p, ack_data_p);

			break;
		}
	}
}
